package com.jiao.datasource.parse;

import cn.hutool.core.util.StrUtil;

import java.util.Arrays;
import java.util.List;

/**
 * sql 解析.
 * @Author Vincent.jiao
 * @Date 2022/5/13 10:24
 */
public class SQLParse {
    public static final List<String> tableNamefilterList = Arrays.asList("(", ")", "INNER JOIN"
            , "LEFT JOIN", "RIGHT JOIN", ",");

    public static final List<Character> filterCharList = Arrays.asList(' ', '\n', '\t');

    public static void main(String[] args) {
        parseSqlStruct("  SELECT \t\t\tdpo_view \t\t\t,dpo_res_subtype          ,dpo_icon_ind          ,dpo_title_ind          ,dpo_lan_ind          ,dpo_desc_ind          ,dpo_instruct_ind          ,dpo_eff_start_datetime_ind          ,dpo_eff_end_datetime_ind          ,dpo_difficulty_ind          ,dpo_time_limit_ind          ,dpo_suggested_time_ind          ,dpo_duration_ind          ,dpo_max_score_ind          ,dpo_pass_score_ind          ,dpo_pgr_start_datetime_ind          ,dpo_pgr_complete_datetime_ind          ,dpo_pgr_last_acc_datetime_ind          ,dpo_pgr_attempt_nbr_ind          ,dpo_max_usr_attempt_ind          ,dpo_instructor_ind          ,dpo_organization_ind          ,dpo_moderator_ind          ,dpo_evt_datetime_ind          ,dpo_evt_venue_ind          ,dpo_status_ind       FROM displayoption WHERE          dpo_res_type = ?           AND dpo_view = ?  ");
        parseSqlStruct("  select sysdate() ");
        parseSqlStruct("  select * from demo ");
    }

    public static SQLStruct parseSqlStruct(String sql) {
        if (StrUtil.isEmpty(sql)) {
            return null;
        }

        //推算第一个单词
        int i = -1, start = -1;
        char[] sqlArr = sql.toCharArray();
        while (++i < sqlArr.length) {
             if(filterCharList.contains(sqlArr[i])) {
                 if(start > -1) {
                     break;
                 } else {
                     continue;
                 }
             }

            start = start == -1 ? i : start;        //定位单词开头
        }
        String type = sql.substring(start, i);

        if (StrUtil.isEmpty(type)) {
            return null;
        }

        SQLStruct sqlStruct = new SQLStruct(sql);
        String execType = type.toUpperCase();;
        String sqlClone = sql.toUpperCase();
        String tableName = null;
        int startInd = -1;

        switch (execType) {
            case SQLStruct.DELETE:
                parseFromStruct(sqlStruct);
                break;
            case SQLStruct.SELECT:
                parseFromStruct(sqlStruct);
                break;
            case SQLStruct.INSERT:
                startInd = sqlClone.indexOf("INTO") + "INTO".length();
                tableName = sql.substring(startInd, sql.indexOf('(', startInd)).trim();
                sqlStruct.setTableName(tableName);
                break;
            case SQLStruct.UPDATE:
                parseUpdateStruct(sqlStruct);

                break;
            default:
                tableName = null;
        }

        sqlStruct.setCommandType(execType);
        return sqlStruct;
    }

    /**
     * 获取表名.
     * @return
     */
    private static void parseFromStruct(SQLStruct sqlStruct) {
        String sqlClone = sqlStruct.getSql().toUpperCase();
        int fromPos = -1, wherePos = -1;

        //使用2个指针去获取一个 token 令牌，然后一路推导出有效的 where
        int groupLeft = 0;
        char[] sqlArr = sqlClone.toCharArray();
        int i = 0;
        for (; i < sqlArr.length; i++) {
            char item = sqlArr[i];

            if(item == '(') {
                ++groupLeft;
            } else if(item == ')') {
                --groupLeft;
            } else if (filterCharList.contains(item)) {
                continue;

            } else if (item != ' ') {
                if(groupLeft > 0) {
                    continue;
                }

                int posS = i;
                while (++i < sqlArr.length && !filterCharList.contains(sqlArr[i])) { }
                String part = sqlClone.substring(posS, i);

                if("FROM".equalsIgnoreCase(part)) {
                    sqlStruct.setColunmSql(sqlStruct.getSql().substring("SELECT".length()  + 1, posS));
                    fromPos = posS + "FROM".length();

                } else if("WHERE".equalsIgnoreCase(part)) {
                    sqlStruct.setTableName(sqlStruct.getSql().substring(fromPos, posS));
                    wherePos = posS + "WHERE".length();

                } else if (i >= sqlArr.length - 1) {
                    if(fromPos == -1) {     //没找到 form
                        sqlStruct.setColunmSql(sqlStruct.getSql().substring("SELECT".length() + 1));

                    } else if(wherePos == -1) {     //没有找到 where
                        sqlStruct.setTableName(sqlStruct.getSql().substring(fromPos));
                    } else {
                        sqlStruct.setWhereSql(sqlStruct.getSql().substring(wherePos));
                    }
                }
            }
        }

//        if(StrUtil.isEmpty(sqlStruct.getWhereSql())) {
//            if(wherePos > -1) {
//                sqlStruct.setWhereSql(sqlStruct.getSql().substring(wherePos));
//            } else if (fromPos > -1)  {
//                sqlStruct.setWhereSql(sqlStruct.getSql().substring(fromPos).trim());
//            }
//        }
    }

    /**
     * 获取表名.
     * @return
     */
    private static void parseUpdateStruct(SQLStruct sqlStruct) {
        String sqlClone = sqlStruct.getSql().toUpperCase();
        String sql = sqlStruct.getSql();
        int startInd = sqlClone.indexOf(SQLStruct.UPDATE) + SQLStruct.UPDATE.length();

        String tableName = sql.substring(startInd, sqlClone.indexOf("SET"));
        sqlStruct.setTableName(tableName.trim());

        sqlStruct.setWhereSql(sql.substring(sqlClone.indexOf("WHERE") + "WHERE".length()));
    }
}



















